#include "game.hpp"
#include "../video/screen.hpp"
#include "../video/Sprite.hpp"
#include "scene.hpp"

namespace yep
{
Game *Game::instance = NULL;

Game::~Game()
{
}

bool Game::run()
{
    // If there isn't a @b screen, it instantiates a new Screen;
	Screen &screen(Screen::getInstance());
    if( !screen ) {
    	screen.setVideoMode( 640, 480, 0, SDL_HWSURFACE );
    }

    YEP_ASSERT( currentScene != NULL );
    // Executes the Scene::setup() to currentScene;
    currentScene->setup( *this );
    // Sets running to true;
    running = true;
    Uint32 timeOnFrameStart = SDL_GetTicks();
    Uint32 currentFPS = 0;

    while( running ) {
        Scene &scene = *currentScene;
        // Call Scene::logic() to currentScene;
        scene.logic( *this );

        // Call Scene::draw() to @b currentScene;
        screen.clear(Color::BLACK);
        scene.draw( *this );
        if( showFPS ) {
            drawFPS( currentFPS );
        }
        screen.flip();

        // If @b currentScene is changed:
        if( &scene != currentScene ) {
            // Call Scene::cleanup() to the old one;
            scene.cleanup( *this );
            // Call Scene::setup() to the new one;
            currentScene->setup( *this );
        }

        Uint32 timeOnFrameEnd = SDL_GetTicks();

        Uint32 expectedInterval = 1000 / fps;
        Uint32 currentInterval = timeOnFrameEnd - timeOnFrameStart;
        if( expectedInterval > currentInterval ) {
            SDL_Delay( expectedInterval - currentInterval );
        }

        Uint32 lastFrameStart = timeOnFrameStart;
        timeOnFrameStart = SDL_GetTicks();
        currentFPS = 1000 / ( timeOnFrameStart - lastFrameStart );
        ++currentFrame;
        Sprite::nextFrame();
    }

    // Sets @b running to false
    running = false;
    // Else Call Scene::cleanup() to currentScene;
    currentScene->cleanup( *this );
    return true;
}

Game::Game()
{
    YEP_ASSERT( instance == NULL );
    instance = this;
    fps = 30;
    showFPS = true;
    currentFrame = 0;
    running = false;
    currentScene = NULL;
}

void Game::drawFPS( unsigned fps )
{
    stringstream s;
    s << fps << " FPS";
    Screen::getInstance().drawText( Vector2::ZERO, Color( Color::LIGHT_RED ).alpha( 127 ), s.str() );
}

}
